package com.ysten.basic.service.system;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.ysten.basic.bean.entity.system.User;
import com.ysten.basic.bean.repository.system.UserDao;
import com.ysten.basic.common.exception.ServiceException;
import com.ysten.basic.common.security.utils.Digests;
import com.ysten.basic.common.utils.DateProvider;
import com.ysten.basic.common.utils.Encodes;
import com.ysten.basic.common.utils.persistence.DynamicSpecifications;
import com.ysten.basic.common.utils.persistence.SearchFilter;
import com.ysten.basic.service.system.ShiroDbRealm.ShiroUser;

/**
 * 用户管理类.
 * 
 * @author 陆小凤
 */
// Spring Service Bean的标识.
@Component
@Transactional(value = "transactionManager")
public class AccountService
{
    
    public static final String HASH_ALGORITHM = "SHA-1";
    
    public static final int HASH_INTERATIONS = 1024;
    
    private static final int SALT_SIZE = 8;
    
    private static Logger logger = LoggerFactory.getLogger(AccountService.class);
    
    private UserDao userDao;
    
    private DateProvider dateProvider = DateProvider.DEFAULT;
    
    /**
     * <获得用户信息列表>
     * 
     * @param searchParams
     * @param pageNumber
     * @param pageSize
     * @return
     */
    public Page<User> getUserList(Map<String, Object> searchParams, int pageNumber, int pageSize)
    {
        PageRequest pageRequest = buildPageRequest(pageNumber, pageSize);
        Specification<User> spec = buildSpecification(searchParams);
        return userDao.findAll(spec, pageRequest);
    }
    
    public List<User> getAllUser()
    {
        return (List<User>)userDao.findAll();
    }
    
    public User getUser(Long id)
    {
        return userDao.findOne(id);
    }
    
    public User findUserByLoginName(String loginName)
    {
        
        Map<String, Object> searchParams = new HashMap<String, Object>();
        searchParams.put("EQ_loginName", loginName);
        Specification<User> spec = buildSpecification(searchParams);
        List<User> userList = userDao.findAll(spec);
        if (!userList.isEmpty())
        {
            return userList.get(0);
        }
        else
        {
            return null;
        }
        
    }
    
    public void registerUser(User user)
    {
        entryptPassword(user);
        user.setRoles("user");
        user.setRegisterDate(dateProvider.getDate());
        userDao.save(user);
    }
    
    public void addSystemUser(User user)
    {
        // entryptPassword(user);
        user.setRegisterDate(dateProvider.getDate());
        userDao.save(user);
    }
    
    public void updateUser(User user)
    {
        if (StringUtils.isNotBlank(user.getPlainPassword()))
        {
            entryptPassword(user);
        }
        userDao.save(user);
    }
    
    public void deleteUser(Long id)
    {
        if (isSupervisor(id))
        {
            logger.warn("操作员{}尝试删除超级管理员用户", getCurrentUserName());
            throw new ServiceException("不能删除超级管理员用户");
        }
        userDao.delete(id);
        
    }
    
    /**
     * 判断是否超级管理员.
     */
    private boolean isSupervisor(Long id)
    {
        return id == 1;
    }
    
    /**
     * 取出Shiro中的当前用户LoginName.
     */
    private String getCurrentUserName()
    {
        ShiroUser user = (ShiroUser)SecurityUtils.getSubject().getPrincipal();
        return user.loginName;
    }
    
    /**
     * 设定安全的密码，生成随机的salt并经过1024次 sha-1 hash
     */
    private void entryptPassword(User user)
    {
        byte[] salt = Digests.generateSalt(SALT_SIZE);
        user.setSalt(Encodes.encodeHex(salt));
        
        byte[] hashPassword = Digests.sha1(user.getPlainPassword().getBytes(), salt, HASH_INTERATIONS);
        user.setPassword(Encodes.encodeHex(hashPassword));
    }
    
    @Autowired
    public void setUserDao(UserDao userDao)
    {
        this.userDao = userDao;
    }
    
    public void setDateProvider(DateProvider dateProvider)
    {
        this.dateProvider = dateProvider;
    }
    
    /**
     * 创建分页请求.
     */
    private PageRequest buildPageRequest(int pageNumber, int pagzSize)
    {
        Sort sort = null;
        return new PageRequest(pageNumber - 1, pagzSize, sort);
    }
    
    /**
     * 创建动态查询条件组合.
     */
    private Specification<User> buildSpecification(Map<String, Object> searchParams)
    {
        Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
        // filters.put("firm.firmId", new SearchFilter("firm.firmId",
        // Operator.EQ, userId));
        Specification<User> spec = DynamicSpecifications.bySearchFilter(filters.values(), User.class);
        return spec;
    }
}
